package dynamicJsonVerifyer;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Pattern;

public class ServiceImpl implements DynamicJsonVerifyService {

    @Autowired
    VerifyMetadataSelecter selecter;
    @Autowired
    VerifyMetadataLoader loader;
    @Autowired
    VerifyerSelecter verifyerSelecter;

    public String execute(String appointTransformerName, String verifyMetadataExpression, JSONObject originalVerifyJson) {
        /*
         * 获取原始数据转换器并转换原始数据
         */
        AppointTransformer appointTransformer = VerifyConfiguration.getAppointTransformer(appointTransformerName);
        JSONObject appointVerifyJson = appointTransformer.transform(originalVerifyJson);
        /*
         * 从原始数据中获取标识变量map, 填充到verifyMetadataExpression中得到校验元数据标识
         */
        Map<String, String> identifierMap = appointTransformer.getIdentifier(originalVerifyJson);
        String verifyMetadataIdentifier = fillVar(verifyMetadataExpression, identifierMap);
        /*
         * 获取元数据所属更新标识（也可以理解组标识或产品标识）
         * 检查是否需要重新加载更新标识下的所有校验元数据
         * 需要则重新加载
         */
        String renewalKey = selecter.getRenewalKey(verifyMetadataIdentifier);
        long versionTime = selecter.getVersionTime(renewalKey);
        if(renewalKey!=null){
            return "没有对应的校验无数据!";
        }
        loader.renewal(selecter, renewalKey, versionTime);

        /*
         * 获取校验元数据
         */
        VerifyMetadata metadata = selecter.getMetadata(verifyMetadataIdentifier);
        if(metadata==null)
            return "没有对应的校验元数据!";

        List<VerifyMetadata.Son> metadataSons = metadata.getSons();


        /*
         * 获取字段的校验数据
         */
        for(VerifyMetadata.Son son : metadataSons){
            String jsonpath = son.getJsonpath();
            FieldVerifyer verifyer = son.getCacheFieldVerifyer();
            JSONObject metadataJson = son.getMetadataJson();
            if(verifyer==null){
                /*
                 * 根据字段元数据获取对应的校验器
                 */
                verifyer = verifyerSelecter.get(metadataJson);
            }
            if(verifyer==null){
                return String.format("字段[%s]没有对应的校验器!", jsonpath);
            }
            /*
             * 进行校验
             */
            if(!verifyer.verify(son.getMetadataJson(), getValueByJsonPath(appointVerifyJson, jsonpath))){
                return String.format("字段[%s]校验不通过!", jsonpath);
            }
        }
        return null;
    }


    /**
     * 填充字符串中的变量
     * @param expression
     * @param varMap
     * @return
     */
    private String fillVar(String expression, Map<String, String> varMap){
        for(String key : varMap.keySet()){
            String key0 = "$"+key;
            if(expression.contains(key0)) {
                expression = expression.replace(key0, varMap.get(key));
            }
        }
        return expression;
    }

    /**
     *
     * @param json
     * @param jsonpath
     * @return
     */
    private Object getValueByJsonPath(JSONObject json, String jsonpath){
        if(StringUtils.isEmpty(json))
            throw new RuntimeException();
        String[] fieldNames = jsonpath.split(".");
        Object value = json;
        for(String fieldName : fieldNames){
            boolean isInteger = value instanceof String && isInteger((String)value);
            if(isInteger){
                value = ((JSONArray)value).get(Integer.valueOf((String)value));
            }else {
                value = ((JSONObject)value).get(fieldName);
            }

        }

        return value;
    }






    /**
     * 判断是否为整数
     * @param str
     * @return
     */
    private static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

}
